from django.db import models
from django import forms
import base64

# Python 2/3 兼容性
import sys
if sys.version_info[0] >= 3:
    unicode = str
    
XOR_KEY = 0x88
encryption_header_notin_field = '+'   #used to encrypt tag not when in modelsfield
encryption_header = '^'
encryption_booter = '$'

#used to encrypt decode not when in modelsfield
def decode_notin_field(value):
    if isinstance(value, (str, unicode)) and value.startswith(encryption_header_notin_field):
        encoded_value = value[len(encryption_header_notin_field):-len(encryption_booter)]
        try:
            if sys.version_info[0] >= 3:
                value = base64.b64decode(encoded_value.encode('utf-8'))
            else:
                value = base64.b64decode(encoded_value)
        except Exception:
            pass  # 如果解码失败，返回原值
    return value

#used to encrypt decode when in modelsfield
def to_python_encrypt(value):
    if isinstance(value, (str, unicode)) and value.startswith(encryption_header) and value.endswith(encryption_booter):
        encoded_value = value[len(encryption_header):-len(encryption_booter)]
        try:
            if sys.version_info[0] >= 3:
                value = base64.b64decode(encoded_value.encode('utf-8')).decode('utf-8')
            else:
                value = base64.b64decode(encoded_value).decode('utf-8')
        except Exception:
            pass  # 如果解码失败，返回原值
    return value

#used to encrypt encode when in and not in modelsfield
def get_prep_value_encrypt(value, encryption_header_tag):
    if not isinstance(value, (str, unicode)):
        return value
        
    encryptstr = value
    
    # 处理字符串类型
    if isinstance(value, str):
        header_bytes = encryption_header.encode('ascii', 'ignore')
        header_notin_bytes = encryption_header_notin_field.encode('ascii', 'ignore') 
        if not (value.encode('utf-8').startswith(header_bytes) or value.encode('utf-8').startswith(header_notin_bytes)):
            if sys.version_info[0] >= 3:
                encoded = base64.b64encode(value.encode('utf-8')).decode('ascii')
                encryptstr = encryption_header_tag + encoded + encryption_booter
            else:
                encryptstr = encryption_header_tag.encode('ascii','ignore') + base64.b64encode(value) + encryption_booter.encode('ascii','ignore')
                encryptstr = encryptstr.decode('unicode-escape')
    
    # 处理unicode类型        
    elif isinstance(value, unicode):
        if not value.startswith(encryption_header) and not value.startswith(encryption_header_notin_field):
            value_bytes = value.encode('UTF-8')
            if sys.version_info[0] >= 3:
                encoded = base64.b64encode(value_bytes).decode('ascii')
                encryptstr = encryption_header_tag + encoded + encryption_booter
            else:
                encryptstr = encryption_header_tag + base64.b64encode(value_bytes) + encryption_booter
    
    return encryptstr

#TODO:not used in form when has chinese
class Base64Field(models.Field):
    # Django 1.8+ 不再需要 __metaclass__ = models.SubfieldBase

    def __init__(self, *args, **kwargs):
        super(Base64Field, self).__init__(*args, **kwargs)

    def db_type(self, connection):
        return 'text'
    
    def to_python(self, value):
        return to_python_encrypt(value)

    def get_prep_value(self, value):
        return get_prep_value_encrypt(value,encryption_header)
    
class XORField(models.Field):
    # Django 1.8+ 不再需要 __metaclass__ = models.SubfieldBase
    
    def __init__(self, *args, **kwargs):
        super(XORField, self).__init__(*args, **kwargs)

    def db_type(self, connection):
        return 'text'
    
    def to_python(self, value):
        #todo improve later
        if isinstance(value, (str, unicode)) and value.startswith(encryption_header) and value.endswith(encryption_booter):
            try:
                # Python 3兼容性修复
                hex_data = value[len(encryption_header):-len(encryption_booter)]
                if sys.version_info[0] >= 3:
                    decoded = bytes.fromhex(hex_data)
                else:
                    decoded = hex_data.decode('hex')
                value = ''.join([chr(x ^ XOR_KEY) for x in decoded])
            except Exception:
                pass  # 如果解密失败，返回原值
        return value

    def get_prep_value(self, value):
        if isinstance(value, (str, unicode)):
            if isinstance(value, unicode):
                value = value.encode('UTF-8')
            if sys.version_info[0] >= 3:
                # Python 3处理
                if isinstance(value, bytes):
                    text_value = value.decode('utf-8')
                else:
                    text_value = value
                hex_value = ''.join([format(ord(x) ^ XOR_KEY, '02x') for x in text_value])
            else:
                # Python 2处理
                hex_value = (''.join([chr(ord(x) ^ XOR_KEY) for x in value])).encode('hex')
            return encryption_header + hex_value + encryption_booter
        return value
    
    
    